package aor2.cpu.blockcontrol.horizontal;

import aor2.components.Register;
import aor2.components.Restorable;
import aor2.cpu.blockcontrol.ConditionSignalSet;
import aor2.cpu.blockcontrol.ControlSignalSet;
import aor2.cpu.blockcontrol.ControlUnitMicroProg;
import aor2.cpu.blockcontrol.MicroMemory;

public class ControlUnitHorizontal2Type extends ControlUnitMicroProg implements
		Restorable {

	private static ControlUnitHorizontal2Type singleton = null;

	public static ControlUnitHorizontal2Type getInstance() {
		if (singleton == null) {
			singleton = new ControlUnitHorizontal2Type(
					MMHorizontalType2.getInstance(), new Register(),
					new Register());
		}
		return singleton;
	}

	private ControlUnitHorizontal2Type(MicroMemory uMem, Register uCnt,
			Register cw) {
		super(uMem, uCnt, cw);
	}

	@Override
	public void generateKMsignals() {
		ConditionSignalSet set = ConditionSignalSet.getInstance();
		if (set.get("regdir1").isActive()) {
			kmadr1 = 0x13;
		} else if (set.get("postinc1").isActive()) {
			kmadr1 = 0x15;
		} else if (set.get("predec1").isActive()) {
			kmadr1 = 0x1a;
		} else if (set.get("index1").isActive()) {
			kmadr1 = 0x1f;
		} else if (set.get("regind1").isActive()) {
			kmadr1 = 0x25;
		} else if (set.get("postincind1").isActive()) {
			kmadr1 = 0x29;
		} else if (set.get("predecind1").isActive()) {
			kmadr1 = 0x30;
		} else if (set.get("indexind1").isActive()) {
			kmadr1 = 0x37;
		}

		if (set.get("regdir2").isActive()) {
			kmadr2 = 0x3f;
		} else if (set.get("postinc2").isActive()) {
			kmadr2 = 0x41;
		} else if (set.get("predec2").isActive()) {
			kmadr2 = 0x46;
		} else if (set.get("index2").isActive()) {
			kmadr2 = 0x4B;
		} else if (set.get("regind2").isActive()) {
			kmadr2 = 0x51;
		} else if (set.get("postincind2").isActive()) {
			kmadr2 = 0x56;
		} else if (set.get("predecind2").isActive()) {
			kmadr2 = 0x5E;
		} else if (set.get("indexind2").isActive()) {
			kmadr2 = 0x66;
		}

		if (set.get("INC").isActive()) {
			kmop = 0x6F;
		} else if (set.get("DEC").isActive()) {
			kmop = 0x77;
		} else if (set.get("ASR").isActive()) {
			kmop = 0x7f;
		} else if (set.get("NOT").isActive()) {
			kmop = 0x87;
		} else if (set.get("JMPIND").isActive()) {
			kmop = 0x8f;
		} else if (set.get("JSRIND").isActive()) {
			kmop = 0x93;
		} else if (set.get("RTI").isActive()) {
			kmop = 0x9b;
		} else if (set.get("RTS").isActive()) {
			kmop = 0x9e;
		} else if (set.get("MOV").isActive()) {
			kmop = 0xa3;
		} else if (set.get("OR").isActive()) {
			kmop = 0xab;
		} else if (set.get("SUB").isActive()) {
			kmop = 0xb4;
		} else if (set.get("BSR").isActive()) {
			kmop = 0xbd;
		} else if (set.get("BNZ").isActive()) {
			kmop = 0xc2;
		} else if (set.get("BRN").isActive()) {
			kmop = 0xc3;
		} else if (set.get("INT").isActive()) {
			kmop = 0xc8;
		} else if (set.get("TRPD").isActive()) {
			kmop = 0xca;
		} else if (set.get("TRPD").isActive()) {
			kmop = 0xcc;
		} else if (set.get("INTE").isActive()) {
			kmop = 0xce;
		} else if (set.get("INTD").isActive()) {
			kmop = 0xd0;
		}
	}

	@Override
	public void setBranchAddress() {
		ba = cw.getState() & 0xFF;
	}

	@Override
	public long getBranchAddress() {
		return cw.getState() & 0xFF;
	}

	@Override
	public void generateBrLd() {
		ConditionSignalSet condss = ConditionSignalSet.getInstance();
		ControlSignalSet ctrlss = ControlSignalSet.getInstance();
		// long step = uCnt.getState();
		branch.setActive((condss.get("PRCOD").isActive() && ctrlss.get(
				"brPRCOD").isActive())
				|| (condss.get("adr0").isActive() && ctrlss.get("bradr0")
						.isActive())
				|| (condss.get("adr1").isActive() && ctrlss.get("bradr1")
						.isActive())
				|| (

				condss.get("notpom1").isActive() && ctrlss.get("brnotpom1")
						.isActive()

				)
				|| (condss.get("notpom2").isActive() && ctrlss.get("brnotpom2")
						.isActive())
				|| (condss.get("MOV").isActive() && ctrlss.get("brMOV")
						.isActive())
				|| (condss.get("immed2").isActive() && ctrlss.get("brimmed2")
						.isActive()

				)
				|| (condss.get("regdir2").isActive() && ctrlss.get("brregdir2")
						.isActive())
				|| (condss.get("eql").isActive() && ctrlss.get("breql")
						.isActive())
				|| (condss.get("notprekid").isActive() && ctrlss.get(
						"brnotprekid").isActive())
				|| (condss.get("pradr").isActive() && ctrlss.get("brpradr")
						.isActive())
				|| (condss.get("prins").isActive() && ctrlss.get("brprins")
						.isActive())// step==0xe6&&
				|| (condss.get("prinm").isActive() && ctrlss.get("brprinm")
						.isActive())// step==0xe9&&
				|| (condss.get("primm").isActive() && ctrlss.get("brprimm")
						.isActive())// step==0xea&&
				|| (ctrlss.get("bruncnd").isActive()

				));
		if (!run.isActive())
			ld.setActive(false);
		else
			ld.setActive(branch.isActive() || brop.isActive()
					|| bradr1.isActive() || bradr2.isActive());
	}

	@Override
	protected void nextuCnt() {
		if (run.isActive()) {
			if (brop.isActive()) {
				uCnt.setState(kmop);
			} else if (bradr1.isActive()) {
				uCnt.setState(kmadr1);
			} else if (bradr2.isActive()) {
				uCnt.setState(kmadr2);
			} else if (branch.isActive()) {
				uCnt.setState(cw.getState() & 0xFF);// ba?
				branch.setActive(false);
			} else {
				uCnt.setState(uCnt.getState() + 1);
			}
		}
	}

	protected void prevuCnt() {
		// TODO
		uCnt.previousClk();
	}

	public void restore(String restorePoint) {
		if (singleton == null)
			singleton = new ControlUnitHorizontal2Type(
					MMHorizontalType2.getInstance(), new Register(),
					new Register());
		String trim = restorePoint.replace(beginTag(), "");
		trim = trim.replace(endTag(), "");
		trim = trim.trim();
		String[] states = trim.split(" ");
		uCnt.setState(Long.parseLong(states[0], 16));
		cw.setState(Long.parseLong(states[1], 16));
	}

	@Override
	public String createRestorePoint() {
		return beginTag() + "\n\t" + Long.toHexString(uCnt.getState()) + " "
				+ Long.toHexString(cw.getState()) + "\n" + endTag();
	}

	@Override
	public String beginTag() {
		return "<HorizControlUnit>";
	}

	@Override
	public String endTag() {
		return "</HorizControlUnit>";
	}

	@Override
	public String phaseInfo() {
		// TODO Auto-generated method stub
		return null;
	}

}
